////////////////////////////////////////////////////////////////
//                                                            //
//  Neoforce Controls                                         //
//                                                            //
////////////////////////////////////////////////////////////////
//                                                            //
//         File: Button.cs                                    //
//                                                            //
//      Version: 0.7                                          //
//                                                            //
//         Date: 11/09/2010                                   //
//                                                            //
//       Author: Tom Shane                                    //
//                                                            //
////////////////////////////////////////////////////////////////
//                                                            //
//  Copyright (c) by Tom Shane                                //
//                                                            //
////////////////////////////////////////////////////////////////


#region //// Using /////////////

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
////////////////////////////////////////////////////////////////////////////
using Microsoft.Xna.Framework.Graphics;
////////////////////////////////////////////////////////////////////////////

#endregion

namespace TomShane.Neoforce.Controls
{ 
  
  #region //// Enums /////////////
  
  ////////////////////////////////////////////////////////////////////////////              
  ///  <include file='Documents/Button.xml' path='Button/Class[@name="SizeMode"]/*' />
  public enum SizeMode
  {
    Normal, 
    Auto,
    Centered,
    Stretched
  }  
  ////////////////////////////////////////////////////////////////////////////

  ////////////////////////////////////////////////////////////////////////////              
  ///  <include file='Documents/Button.xml' path='Button/Class[@name="SizeMode"]/*' />
  public enum ButtonMode
  {
    Normal,
    PushButton
  }
  ////////////////////////////////////////////////////////////////////////////

    public enum ButtonTextMode
    {
        Normal,
        Centered
    }
  #endregion

  #region //// Classes ///////////
  
  ////////////////////////////////////////////////////////////////////////////              
  ///  <include file='Documents/Button.xml' path='Button/Class[@name="Glyph"]/*' />          
  public class Glyph
  {
    ////////////////////////////////////////////////////////////////////////////  
    public Texture2D Image = null;
    public SizeMode SizeMode = SizeMode.Stretched;
    public Color Color = Color.White;
    public Point Offset = Point.Zero;  
    public Rectangle SourceRect = Rectangle.Empty;
    ////////////////////////////////////////////////////////////////////////////  
    
    ////////////////////////////////////////////////////////////////////////////  
    public Glyph(Texture2D image)
    {
      Image = image;
    }
    ////////////////////////////////////////////////////////////////////////////  
    
    ////////////////////////////////////////////////////////////////////////////  
    public Glyph(Texture2D image, Rectangle sourceRect): this(image)
    {      
      SourceRect = sourceRect;
    }
  }
  ////////////////////////////////////////////////////////////////////////////  
    
  ////////////////////////////////////////////////////////////////////////////  
  ///  <include file='Documents/Button.xml' path='Button/Class[@name="Button"]/*' />          
  public class Button: ButtonBase
  {

    #region //// Consts ////////////

    ////////////////////////////////////////////////////////////////////////////
    private const string skButton = "Button";
    private const string lrButton = "Control";
    ////////////////////////////////////////////////////////////////////////////

    #endregion

    #region //// Fields ////////////

    ////////////////////////////////////////////////////////////////////////////              
    private Glyph glyph = null;
    private ModalResult modalResult = ModalResult.None;
    private ButtonMode mode = ButtonMode.Normal;
    private bool pushed = false;
      private int paddingLeft = 0;
      private int paddingTop = 0;
      ButtonTextMode btnTextMode = ButtonTextMode.Centered;
      protected int CalculatedPaddingLeft = 0;
      protected int CalculatedPaddingTop = 0;
      private SpriteFont font;
    ////////////////////////////////////////////////////////////////////////////

    #endregion

    #region //// Properties ////////

    ////////////////////////////////////////////////////////////////////////////        
    public Glyph Glyph
    {
      get { return glyph; }
      set 
      { 
        glyph = value;
        if (!Suspended) OnGlyphChanged(new EventArgs());        
      }
    }
    ////////////////////////////////////////////////////////////////////////////
    
    ////////////////////////////////////////////////////////////////////////////
    public ModalResult ModalResult
    {
      get { return modalResult; }
      set { modalResult = value; }
    }
    ////////////////////////////////////////////////////////////////////////////
      public override string Text
      {
          get { return base.Text; }
          set
          {
              string temp = value;
              if (!string.IsNullOrEmpty(temp))
              {
                  List<string> lines = SplitTextToWidth(font, temp, Width - PaddingLeft - CalculatedPaddingLeft);
                  temp = "";
                  foreach (string line in lines)
                  {
                      temp += line + Environment.NewLine;
                  }
                  temp = temp.Substring(0, temp.Length - 2);
              }
              base.Text = temp;
          }
      }
    ////////////////////////////////////////////////////////////////////////////
    public ButtonMode Mode
    {
      get { return mode; }
      set { mode = value; }
    }
    ////////////////////////////////////////////////////////////////////////////
    
    ////////////////////////////////////////////////////////////////////////////
    public bool Pushed
    {
      get { return pushed; }
      set 
      { 
        pushed = value; 
        Invalidate();
      }      
    }
    ////////////////////////////////////////////////////////////////////////////

      public int PaddingLeft
      {
          get { return paddingLeft; }
          set { paddingLeft = value; }
      }

      public int PaddingTop
      {
          get { return paddingTop; }
          set { paddingTop = value; }
      }

      public ButtonTextMode ButtonTextMode
      {
          get { return btnTextMode; }
          set { btnTextMode = value; }
      }

      public Alignment TextAlignment
      {
          get { return Skin.Layers[lrButton].Text.Alignment; }
          set { Skin.Layers[lrButton].Text.Alignment = value; }
      }

      public override int Height
      {
          get
          {
              return base.Height;
          }
          set
          {
              Text = Text;
              base.Height = value;
          }
      }

      public override int Width
      {
          get
          {
              return base.Width;
          }
          set
          {
              Text = Text;
              base.Width = value;
          }
      }

      #endregion

    #region //// Events ////////////

    ////////////////////////////////////////////////////////////////////////////                 
    public event EventHandler GlyphChanged;
    ////////////////////////////////////////////////////////////////////////////

    #endregion

    #region //// Construstors //////

    ////////////////////////////////////////////////////////////////////////////       
    public Button(Manager manager): base(manager)
    {            
      SetDefaultSize(72, 24);      
    }    
    ////////////////////////////////////////////////////////////////////////////

    #endregion

    #region //// Destructors ///////

    ////////////////////////////////////////////////////////////////////////////
    protected override void Dispose(bool disposing)
    {
      if (disposing)
      {
      }
      base.Dispose(disposing);
    }
    ////////////////////////////////////////////////////////////////////////////

    #endregion
    
    #region //// Methods ///////////
    
    ////////////////////////////////////////////////////////////////////////////
    public override void Init()
    {      
      base.Init();        
    }
    ////////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////////
    protected internal override void InitSkin()
    {
      base.InitSkin();
      Skin = new SkinControl(Manager.Skin.Controls[skButton]);
      font = (Skin.Layers["Control"].Text != null) ? Skin.Layers["Control"].Text.Font.Resource : null;
    }
    ////////////////////////////////////////////////////////////////////////////
    
    ////////////////////////////////////////////////////////////////////////////
    protected override void DrawControl(Renderer renderer, Rectangle rect, GameTime gameTime)
    {                    

      if (mode == ButtonMode.PushButton && pushed)
      {
        SkinLayer l = Skin.Layers[lrButton];
        renderer.DrawLayer(l, rect, l.States.Pressed.Color, l.States.Pressed.Index);
        if (l.States.Pressed.Overlay)
        {
          renderer.DrawLayer(l, rect, l.Overlays.Pressed.Color, l.Overlays.Pressed.Index);          
        }                
      }
      else
      {
        base.DrawControl(renderer, rect, gameTime);
      }
    
      SkinLayer layer = Skin.Layers[lrButton];                                  
      SpriteFont font = (layer.Text != null && layer.Text.Font != null) ? layer.Text.Font.Resource : null;
      Color col = Color.White;              
      int ox = 0; int oy = 0;
    
      if (ControlState == ControlState.Pressed)
      {       
        if (layer.Text != null) col = layer.Text.Colors.Pressed;
        ox = 1; oy = 1;
      }                               
      if (glyph != null)
      {
        Margins cont = layer.ContentMargins;
        Rectangle r = new Rectangle(rect.Left + cont.Left, 
                                    rect.Top + cont.Top, 
                                    rect.Width - cont.Horizontal, 
                                    rect.Height - cont.Vertical);
        renderer.DrawGlyph(glyph, r);
      }
      else
      {
          Rectangle r;
          if (btnTextMode == ButtonTextMode.Centered)
          {
              r = rect;
          }
          else
          {
              r = ControlRect;
          }
          if (PaddingLeft != 0 || PaddingTop != 0 || CalculatedPaddingLeft != 0 || CalculatedPaddingTop != 0)
          {
              r = new Rectangle(r.X+paddingLeft+CalculatedPaddingLeft,r.Y+paddingTop+CalculatedPaddingTop,r.Width-paddingLeft,r.Height-paddingTop);
          }
        renderer.DrawString(this, layer, Text, r, true, ox, oy);
      }       
    }
    ////////////////////////////////////////////////////////////////////////////
    public List<string> SplitTextToWidth(SpriteFont font, string text, int width)
    {
        List<string> output = new List<string>();
        if (font.MeasureString(text).X <= width)
        {
            output.Add(text);
            return output;
        }
        string tempStr = "";

            List<string> words = new List<string>();
            words.AddRange(text.Split(' '));
            for (int i = 0; i < words.Count; i++)
            {
                tempStr += words[i] + " ";
                if (font.MeasureString(tempStr + (i < words.Count - 1 ? words[i + 1] : "") + "a").X >= width)
                {
                    output.Add(tempStr.Trim());
                    tempStr = "";
                }
            }
            output.Add(tempStr.Trim());
        return output;
    }
    ////////////////////////////////////////////////////////////////////////////
    private void OnGlyphChanged(EventArgs e)
    {
      if (GlyphChanged != null) GlyphChanged.Invoke(this, e);
    }
    //////////////////////////////////////////////////////////////////////////// 

    //////////////////////////////////////////////////////////////////////////// 
    protected override void OnClick(EventArgs e)
    {
      MouseEventArgs ex = (e is MouseEventArgs) ? (MouseEventArgs)e : new MouseEventArgs();      
      
      if (ex.Button == MouseButton.Left || ex.Button == MouseButton.None)
      {
        pushed = !pushed;
      }  
      
      base.OnClick(e);           
      
      if ((ex.Button == MouseButton.Left || ex.Button == MouseButton.None) && Root != null)
      {
        if (Root is Window)
        {
          Window wnd = (Window)Root;
          if (ModalResult != ModalResult.None)
          {            
            wnd.Close(ModalResult);
          }
        }        
      }
    }
    ////////////////////////////////////////////////////////////////////////////   
  
    #endregion  
     
  }
  
  #endregion
  
}
